package com.extremelylargepackage;

import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import android.content.Context;

import com.extremelylargepackage.entity.Enemy;
import com.extremelylargepackage.entity.Entity;
import com.extremelylargepackage.entity.Entity.Status;
import com.extremelylargepackage.entity.EntityFactory;
import com.extremelylargepackage.entity.HealthBar;
import com.extremelylargepackage.entity.Player;
import com.extremelylargepackage.entity.Projectile;
import com.extremelylargepackage.entity.ScrollingBackground;
import com.extremelylargepackage.level.Level;
import com.extremelylargepackage.level.LevelParser;
import com.extremelylargepackage.level.MalformedLevelException;

/**
 * Keeps track of game state, eg. entities, score
 */
public class GameState 
{
	private HealthBar _playerHealthBar;
	private Collection<Enemy> _enemies;
	private Collection<Entity> _scenery;
	private Player _player;
	private Level _level;
	private boolean _actionPaused;

	/**
	 * Where old entities go to die.
	 */
	private Collection<Entity> _junkyard;

	int score;

	public GameState(String levelName, boolean local)
	{
		_enemies = new LinkedList<Enemy>();
		_player = new Player(GameResources.getResource("starter_ship"), (float)(.5 * GameResources.SCREEN_WIDTH), (float)(.9 * GameResources.SCREEN_HEIGHT));
		EntityFactory.setName(_player, "Player");
		_playerHealthBar = new HealthBar(_player, 0, 0);
		_scenery = new LinkedList<Entity>();
		_junkyard = new LinkedList<Entity>();

		try {
			_level = LevelParser.parseLevel(levelName, local);
			_level.setGameState(this);
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedLevelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public Collection<Enemy> getEnemies()
	{
		return _enemies;
	}
	
	public Collection<Entity> getScenery()
	{
		return _scenery;
	}

	public Player getPlayer()
	{
		return _player;
	}

	public HealthBar getHealthbar()
	{
		return _playerHealthBar;
	}
	public Collection<Entity> getJunkyard()
	{
		return _junkyard;
	}

	/**
	 * Checks field for collisions, and when found fires the onCollision event for one(?)
	 * of the entities
	 */
	public void checkCollisions() 
	{
		for(Enemy enemy : _enemies)
		{
			if(enemy.getStatus() == Entity.Status.alive)
			{
				if(_player.collidesWith(enemy))
				{
					_player.onCollision(enemy);
					enemy.onCollision(_player);
				}
	
				for(Projectile proj: _player.getWeapon().getProjectiles())
				{
					if(proj.collidesWith(enemy) && proj.getStatus() == Status.alive)
					{
						enemy.onCollision(proj);
						proj.onCollision(enemy);
					}
				}
				
				Projectile special = _player.getSpecialProjectile();
				if(special != null && special.getStatus() == Status.alive)
				{
					if(special.collidesWith(enemy))
					{
						enemy.onCollision(special);
						special.onCollision(enemy);
					}
				}
			}
			
			//Dead enemies can have live projectiles.
			if(enemy.hasWeapon())
			{
				for(Projectile proj: enemy.getWeapon().getProjectiles())
				{
					if(proj.collidesWith(_player) && proj.getStatus() == Status.alive)
					{
						_player.onCollision(proj);
						proj.onCollision(_player);
					}
				}
			}
		}
	}

	public void spawnEnemy(Enemy e) {
		_enemies.add(e);
	}

	public void spawnScenery(Entity e)
	{
		_scenery.add(e);
	}

	public Level getLevel()
	{
		return _level;
	}
	
	public ScrollingBackground getBackground()
	{
		return _level.getBackground();
	}
	
	public boolean actionPaused()
	{
		return _actionPaused;
	}
	
	///////////////////////////////////////////////////////////////////////
	// CommandEvent helper methods go here
	///////////////////////////////////////////////////////////////////////
	
	public void setBackgroundScrollSpeed(int speed)
	{
		_level.getBackground().setDirY(speed);
	}
	
	public void setPlayerDestination(float x, float y)
	{
		_player.setDestination(x, y);
	}
	
	public void setPlayerWeaponEnabled(boolean enable)
	{
		_player.getWeapon().setWeaponEnabled(enable);
	}
	
	public void setActionPaused(boolean pause)
	{
		_actionPaused = pause;
	}

	public void saveState(Context context)
	{
		GameStateSaver gss = new GameStateSaver(context);
		gss.writePlayer(_player.getState());

		for(Enemy enemy : _enemies) {
			gss.writeEnemy(enemy.getState());
		}

		for(Entity scenery : _scenery) {
			gss.writeScenery(scenery.getState());
		}

		gss.close();
	}
}
